package com.example.esredisrabbitmqdemo.service;

import com.example.esredisrabbitmqdemo.dao.UserMapper;
import com.example.esredisrabbitmqdemo.message.MessageProduct;
import com.example.esredisrabbitmqdemo.pojo.User;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.WildcardQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;

/**
 * @BelongsProject: es-redis-rabbitmq-demo
 * @BelongsPackage: com.example.esredisrabbitmqdemo.service
 * @Author: 江岸
 * @CreateTime: 2020-07-04 15:09
 * @Description:
 */

@Transactional //开启事务
@Service
public class UserServiceImpl implements UserService{
    @Autowired
    private UserMapper userMapper;

    @Autowired
    MessageProduct messageProduct;

    @Autowired
    UserServiceForElasticsearch userServiceES;
    /**
     *
     * @param id
     * @return
     * 通过id查询 当查询结果为null时不存入缓存，免得报错
     */
    @Override
    @Cacheable(value="user",key="#id",unless = "#result == null ")
    public User queryById(int id) {
        //先走redis
        //再走ES
        Optional<User> byId = userServiceES.findById(id);
        User user = null;
        try {
            user  = byId.get();
        }catch (NoSuchElementException e){
            System.out.println("ES查不到走sql");
            //get无值，报异常。再走mysql
            user = userMapper.queryById(id);
        }
        return user;
    }

    //增
    @Override
    public String add(User user) {
        //先增数据库，增加成功再发送消息队列
        //返回值为主键生成策略的主键
        int add = userMapper.add(user);
        //发送消息
        messageProduct.sent(user.getId()+"");
        return ""+add;
    }

    //删
    @CacheEvict(value="user",key="#id",beforeInvocation=true) //调用该方法之前，清除缓存，因为消息队列太快了。
    public String delete(int id){
        int delete = userMapper.delete(id);
        if(delete>0){
            //成功，发送消息队列让ES删除
            messageProduct.sentDel(id+"");
            return "success";
        }
        return "failed";

    }

    //改
    @CacheEvict(value="user",key="#user.id",beforeInvocation=true) //调用该方法之前，清除缓存，因为消息队列太快了。
    public String update(User user){
        int update = userMapper.update(user);
        if(update>0){
            //成功，发送消息队列让ES更新
            messageProduct.sent(user.getId()+"");
            return "success";
        }
        return "failed";
    }

    //查询所有，不走缓存
    @Override
    public List<User> findAll() {
        Iterable<User> all = userServiceES.findAll();
        List<User> arr = new ArrayList<>();
        //把迭代器中的User对象添加到arr集合
        all.forEach(arr::add);
        if(arr.size()==0){
            //如果ES查不到，走数据库
            System.out.println("如果ES查不到，走数据库");
            arr = userMapper.findAll();
        }
        return arr;
    }

    //根据字符串模糊查询
    @Override
    public List<User> likeSearch(String info) {
        info = "*"+info+"*";
        //搜索名字中含有字符串的文档
        WildcardQueryBuilder queryBuilder1 = QueryBuilders.wildcardQuery("username", info);
        //搜索密码中含有字符串的文档
        WildcardQueryBuilder queryBuilder2 = QueryBuilders.wildcardQuery("password", info);
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //相当于or
        boolQueryBuilder.should(queryBuilder1);
        boolQueryBuilder.should(queryBuilder2);
        Iterable<User> search = userServiceES.search(boolQueryBuilder);
        List<User> arr = new ArrayList<>();
        //把迭代器中的User对象添加到arr集合
        search.forEach(arr::add);
        return arr;
    }
}
